/**
 * this class is The Commands class that performs the commands from the interface's user
 *
 */
package Command;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import Algo.Algo;
import DataBase.MenuTag_File;
import DirectsDB.MenuDirects;
import Observing.Observing;
/**
* Description : this class connect the commands and the interfaces: Gui and WEB
* <p>
*
*@author Danielle and Yeala
*/
public class  MainCommand {
	private static BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("ProjectExec.xml"));	
	static MenuTag_File dataBase;
	static Observing observer;
	static MenuDirects dirDB;
	static boolean isStarted=false;
	private static ArrayList<Algo>  algoList=new ArrayList<Algo>();
	private static Init init;	
	private static boolean firstTimeStartInit=true;
	
	/**
	* Description Constructor 
	* @throws Exception
	*/
	public MainCommand() throws Exception{
		dataBase=(MenuTag_File)beanFactory.getBean("DataBase");
		observer=(Observing)beanFactory.getBean("Observing");
		dirDB=(MenuDirects)beanFactory.getBean("DirectsDB");
		init=(Init)beanFactory.getBean("Init");	
		init.startParam(dataBase,dirDB,algoList);
		/// load algo
		File dir = new File("algo"); /////////////change the dir if you want...
		String[] children = dir.list();
		if (children == null) { // Either dir does not exist or is not a directory 
		} else { 
			for (int i=0; i<children.length; i++) { // Get filename of file or directory 
				String filename = children[i]; 
				if (filename.endsWith(".class")){
					addAlgo(filename.split(".class")[0]);
				}
			} 
		}/*********/
	}
	
	/**
	* Description cloase all commands 
	*/
	public void closMainCommand()
	{
		observer.stopObserver();
		stopInit();
		
	}
	
	
	/**
	* Description adding direct to listener 
	* @param String source
	*/
	public void addSource(String source){	
		if(isStarted)
		{
			stopObserver();
			observer.addSource(source,dirDB);
			startObserver();
		}
		else
			observer.addSource(source,dirDB);
	}
	
	/**
	* Description delete Source 
	* @param String source
	*/
	public void deleteSource(String source){
		if(isStarted)
		{
			stopObserver();
			observer.deleteSource(source,dirDB);
			startObserver();
		}
		else
			observer.deleteSource(source,dirDB);
	}
	
	/**
	* Description return All Source 
	* @return String[]
	*/
	public String[] returnAllSource(){
		return observer.returnAllSource(dirDB);
	}
	
	/**
	* Description start Observer 
	* @return boolean
	*/
	public boolean startObserver(){
		if (isStarted)
			return false;	
		isStarted=true;
		observer.startObserver(algoList,dataBase,dirDB);
		return true;
	}
	
	/**
	* Description stop Observer 
	* @return boolean
	*/
	public boolean stopObserver(){
		if (!isStarted)
			return false;
		isStarted=false;
		observer.stopObserver();
		return true;
	}
	
	/**
	* Description add Algo 
	* @param String algoName
	* @throws Exception
	*/
	public void addAlgo(String algoName) throws Exception  {
		File f=new File("algo/");//D:\\myClasses\\");//"/workspace/theTagWorldProject/myClasses/");// some folder's path like "D:\\myClasses\\"
        URL url;
        url = f.toURL();
        //--> "file:/D:/myClasses/..."
        URL[] urls=new URL[]{url};
        // create a new class loader for this directory
        ClassLoader cl=new URLClassLoader(urls);
        // load the class file "MyAlgo.class"
        Class<Algo> c = (Class<Algo>) cl.loadClass(algoName);
        algoList.add( c.newInstance());//c.newInstance();
	}
	
	/**
	* Description delete Algo 
	* @param String algoName
	*/
	public void deleteAlgo(String algoName){
		Iterator<Algo> algo_iter = algoList.iterator();	
		Algo algo;
		while (algo_iter.hasNext()){
			algo=algo_iter.next();
			if ((algo.toString()).equals(algoName)){
					algoList.remove(algo);
					break;
			}
		}
	}
	
	/**
	* Description delete All Algo 
	*/
	public void deleteAllAlgo(){
		algoList.clear();
	}
	
	/**
	* Description show all Algo 
	* @return String[]
	*/
	public String[] showAlgo(){
		String tmp="";
		boolean flag=false;
		Iterator<Algo> algo_iter = algoList.iterator();	
		while (algo_iter.hasNext()){
			if (flag){
				tmp=tmp+"."+(algo_iter.next()).toString();
			}else{
				flag=true;
				tmp=(algo_iter.next()).toString();
			}
		}
		if (!flag)
			return null;
		String algo[]=tmp.split("\\.");
		return algo;
	}
	
	/**
	* Description stop Init 
	*/
	public void stopInit(){	
		init.stopInit();
	}
	
	/**
	* Description pause the Init 
	*/
	public void pauseInit(){		
		init.pause();
	}
	
	/**
	* Description set the flag firstTimeStartInit to be true 
	*/
	public void setFirstTimeStartInit()
	{
		firstTimeStartInit=true;
	}
	/**
	* Description reStart the Init 
	*/
	public void reStartInit(){	
		if(firstTimeStartInit)
		{
			init.start();
			firstTimeStartInit=false;
		}
		else
			init.cont();
	}
	
	/**
	* Description delete the Data Base 
	*/
	public void deleteDB(){
		dataBase.deleteDB();
	}
	
	public String[] ShoeFilesByTag(String Tag){
		return dataBase.AllFilesInTag(Tag);
	}
	
	public String[] AllTags(){
		return dataBase.getTags();
	}
	
	/**
	* Description return Precent of Init 
	* @return int
	*/
	public int returnPrecentInit(){
		return init.getPrecent();
	}
	
	/**
	* Description algo Discreption 
	* @param String algoName
	* @return String
	*/
	public String algoDiscreption(String algoName){
		Iterator<Algo> algo_iter = algoList.iterator();	
		Algo algo=null;
		while (algo_iter.hasNext()){
			algo=algo_iter.next();
			if ((algo.toString()+".class").equals(algoName)){
					
					return algo.descript();
			}
		}
		if (algo==null)
			return "";
		return algo.descript();
	}
	

}
